package com.lnj.community.aspect;

import com.lnj.community.dao.entity.User;
import com.lnj.community.utiles.HostHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.text.SimpleDateFormat;
import java.util.Date;

@Component
@Aspect
public class ServiceLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(ServiceLogAspect.class);
    /**
     * 定义一个切入点，用于拦截com.lnj.community.service包下的所有类的所有方法
     * 第一个*表示任意返回值
     * 第二个*表示任意类
     * 第三个*表示任意方法
     * ..表示任意参数
     */
    @Pointcut("execution(* com.lnj.community.service.*.*(..))")
    public void pointcut() {

    }
    @Pointcut("execution(* com.lnj.community.controller.*.*(..))")
    public void pointcut2() {

    }

    /**
     * 定义一个通知，用于把当前用户的信息存入ThreadLocal中
     * @param joinPoint 连接点
     */
    @After("pointcut2()")
    public void after(JoinPoint joinPoint) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = null;
        if (auth != null && auth.isAuthenticated() && !(auth.getPrincipal() instanceof String)) {
            user = (User) auth.getPrincipal();
            if (user != null) {
                HostHolder.setUser(user);
            }
        }
    }

    /**
     * 定义一个通知，用于记录方法的执行时间
     */
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        // 检查是否有请求上下文 获取请求相关信息
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 如果是Servlet请求，获取IP地址等信息
        if (requestAttributes instanceof ServletRequestAttributes) {
            ServletRequestAttributes sra = (ServletRequestAttributes) requestAttributes;
            String ip = sra.getRequest().getRemoteHost();
            String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            String target = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
            logger.info(String.format("用户[%s],在[%s],访问了[%s].", ip, now, target));
        } else {
            // 非 Web 请求线程，记录日志但不获取 IP 等信息
            String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            String target = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
            logger.info(String.format("在[%s],调用了[%s].", now, target));
        }
    }
}
